package com.tulink.yichutu.biz;

import com.alibaba.fastjson.JSONObject;
import com.tulink.yichutu.dto.CashCodeDto;
import com.tulink.yichutu.dto.CashCodeGeneratorParamsDto;
import com.tulink.yichutu.dto.GoodsDto;
import com.tulink.yichutu.entity.WxVipCashCouponEntity;
import com.tulink.yichutu.entity.WxVipGoodsEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.Charsets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 超级管理员命令方法
 *
 * @author wanchaopeng
 */
@Slf4j
@Component
public class CmdBiz {

    private final static int commandTimeout = 60;
    public final static String cmdQueryCommand = "query-command";
    public final static String cmdQueryGoodsList = "query-goods-list";
    public final static String cmdGeneratorCashCode = "generator-cash-code-*";
    public final static String cmdQueryCashCodeByName = "query-cash-code-by-name-*";
    public final static String cmdQueryCashCodes = "query-cash-codes-*";
    public final static String cmdDeleteCashCodeByName = "delete-cash-code-by-name-*";
    public final static String cmdDeleteCashCodes = "delete-cash-codes-*";
    public final static String cmdChangeUserVipDate = "change-user-vip-date-*";
    public final static String cmdExchangeVip = "CC-*";

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private GoodsBiz goodsBiz;
    @Autowired
    private CashCouponBiz cashCouponBiz;

    private List<String> supperOpenIds = new ArrayList<>();
    @Value("${wx.supperOpenIds}")
    private void setSupperOpenIds(String value) {
        supperOpenIds.addAll(Arrays.asList(value.split(",")));
    }
    @Value("${wx.supperCmdUrl}")
    private String supperCmdUrl;
    @Value("${wx.appid}")
    private String appid;

    public List<String> getSupperCommands() {
        return Arrays.asList(
                cmdQueryCommand,
                cmdQueryGoodsList,
                cmdGeneratorCashCode,
                cmdQueryCashCodeByName,
                cmdQueryCashCodes,
                cmdDeleteCashCodeByName,
                cmdDeleteCashCodes,
                cmdChangeUserVipDate
        );
    }

    public Boolean isSupperOpenId(String openId) {
        return supperOpenIds.contains(openId);
    }

    public String addCommand(String command, Object params) {
        String tempCommand = UUID.randomUUID().toString();
        String key = getCommandKey(tempCommand);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("command", command);
        jsonObject.put("params", JSONObject.toJSONString(params));
        BoundValueOperations boundValueOperations = redisTemplate.boundValueOps(key);
        boundValueOperations.set(JSONObject.toJSONString(jsonObject));
        boundValueOperations.expire(commandTimeout, TimeUnit.SECONDS);

        return String.format(
                "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s" +
                        "&redirect_uri=%s" +
                        "&response_type=code&scope=snsapi_base&state=&connect_redirect=1&connect_redirect=1#wechat_redirect",
                appid,
                urlEncode(String.format("%s?command=%s", supperCmdUrl, tempCommand))
                );
    }

    public String command(String tempCommand) {
        String key = getCommandKey(tempCommand);
        BoundValueOperations boundValueOperations = redisTemplate.boundValueOps(key);
        Object obj = boundValueOperations.get();
        if (obj == null) {
            return "命令已过期";
        }
        JSONObject jsonObject = JSONObject.parseObject(obj.toString());
        String command = jsonObject.getString("command");
        String params = jsonObject.getString("params");
        switch (command) {
            case cmdQueryGoodsList:
                return queryGoodsList();
            case cmdGeneratorCashCode:
                return generatorCashCodes(params);
            case cmdQueryCashCodeByName:
                return queryCashCodeByName(params);
            case cmdQueryCashCodes:
                return queryCashCodes(params);
            default:
                return "命令不支持：" + command;
        }
    }

    private String queryGoodsList() {
        List<WxVipGoodsEntity> goodsEntities = goodsBiz.getGoods();
        return JSONObject.toJSONString(
                goodsEntities.stream().map(p -> {
                    GoodsDto goodsDto = new GoodsDto();
                    goodsDto.setId(p.getId());
                    goodsDto.setPrice(p.getPrice());
                    goodsDto.setName(p.getName());
                    goodsDto.setValue(p.getValue());
                    goodsDto.setIndex(p.getIndex());
                    return goodsDto;
                }).collect(Collectors.toList()));
    }

    private String generatorCashCodes(String params) {
        CashCodeGeneratorParamsDto paramsDto = JSONObject.parseObject(params, CashCodeGeneratorParamsDto.class);
        WxVipGoodsEntity goodsEntity = goodsBiz.getById(paramsDto.getGoodsId());
        if(goodsEntity == null) {
            return "商品不存在";
        }
        if(cashCouponBiz.hasName(paramsDto.getName())) {
            return "名称已存在";
        }
        List<WxVipCashCouponEntity> cashCouponEntities = cashCouponBiz.generatorCode(
                paramsDto.getName(),
                paramsDto.getCount(),
                goodsEntity);
        paramsDto.setCodes(cashCouponEntities.stream().map(WxVipCashCouponEntity::getCode).collect(Collectors.toList()));
        return JSONObject.toJSONString(paramsDto);
    }

    private String queryCashCodeByName(String params) {
        String paramsDto = JSONObject.parseObject(params, String.class);
        List<WxVipCashCouponEntity> cashCouponEntities = cashCouponBiz.getByName(paramsDto);
        if(CollectionUtils.isEmpty(cashCouponEntities)) {
            return "没有找到";
        }
        List<CashCodeDto> cashCodes = cashCouponEntities.stream().map(p -> {
            CashCodeDto codeDto = new CashCodeDto();
            codeDto.setCode(p.getCode());
            codeDto.setGoodsId(p.getGoodsId());
            codeDto.setStatus(p.getStatus());
            codeDto.setName(p.getName());
            return codeDto;
        }).collect(Collectors.toList());
        return JSONObject.toJSONString(cashCodes);
    }

    private String queryCashCodes(String params) {
        List<String> paramsDto = JSONObject.parseArray(params, String.class);
        List<WxVipCashCouponEntity> cashCouponEntities = cashCouponBiz.getByCodes(paramsDto.toArray(new String[0]));
        if(CollectionUtils.isEmpty(cashCouponEntities)) {
            return "没有找到";
        }
        List<CashCodeDto> cashCodes = cashCouponEntities.stream().map(p -> {
            CashCodeDto codeDto = new CashCodeDto();
            codeDto.setCode(p.getCode());
            codeDto.setGoodsId(p.getGoodsId());
            codeDto.setStatus(p.getStatus());
            codeDto.setName(p.getName());
            return codeDto;
        }).collect(Collectors.toList());
        return JSONObject.toJSONString(cashCodes);
    }

    private String getCommandKey(String command) {
        return "supper-cmd:" + command;
    }

    private String urlEncode(String url) {
        try {
            return URLEncoder.encode(url, Charsets.UTF_8.name());
        } catch (UnsupportedEncodingException e) {
            log.error("urlEncode", e);
        }
        return url;
    }
}
